package com.cn.gmall.payment.controller;

import com.alipay.api.internal.util.AlipaySignature;

import com.cn.gmall.common.result.Result;
import com.cn.gmall.model.enums.PaymentType;
import com.cn.gmall.model.payment.PaymentInfo;
import com.cn.gmall.payment.config.AliPayClientConfig;
import com.cn.gmall.payment.service.AlipayService;
import com.cn.gmall.payment.service.PaymentInfoService;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Controller
@RequestMapping("/api/payment/alipay")
public class AlipayController {
    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private AlipayService alipayService;

    @Autowired
    private PaymentInfoService paymentInfoService;

    /**
     * /api/payment/alipay/closePay/{orderId}
     * 给支付宝发请求-->关闭支付支付记录
     * @param orderId
     * @return
     */
    @GetMapping("/closePay/{orderId}")
    @ResponseBody
    public Boolean closePay(@PathVariable Long orderId){


        return alipayService.closePay(orderId);
    }

    /**
     * /api/payment/alipay/checkPayment/{orderId}
     * 给支付宝发请求-->查询支付支付记录
     * @param orderId
     * @return
     */
    @GetMapping("/checkPayment/{orderId}")
    @ResponseBody
    public Boolean checkPayment(@PathVariable Long orderId){


        return alipayService.checkPayment(orderId);
    }




    /** /api/payment/alipay/getPaymentInfo/{outTradeNo}
     * 获取支付记录信息(本地存储的订单信息)
     * @param outTradeNo
     * @return
     */
    @GetMapping("/getPaymentInfo/{outTradeNo}")
    @ResponseBody
    public PaymentInfo getPaymentInfo(@PathVariable String outTradeNo){

        PaymentInfo paymentInfo= paymentInfoService.getPaymentInfo(outTradeNo,null);

        return paymentInfo;
    }


    /***   退款
     *    http://localhost:8205/api/payment/alipay/refund/20
     * @param orderId
     * @return
     */
    @GetMapping("/refund/{orderId}")
    @ResponseBody
    public Result refund(@PathVariable Long orderId) {
//退款接口
        boolean flag = alipayService.refund(orderId);

        return  Result.ok(flag);
    }


    /**
     * 异步回调
     *
     * @param result
     * @return
     */
    //http://ty2zwh.natappfree.cc/api/payment/alipay/callback/notify
    @SneakyThrows
    @PostMapping("/callback/notify")
    @ResponseBody
    public String callbackNotify(@RequestParam Map<String, String> result) {

//        System.out.println("result = " + result); 测试支付宝 异步请求 返回的参数
//验签

        Map<String, String> paramsMap = result; //将异步通知中收到的所有参数都存放到map中
        boolean signVerified = AlipaySignature.rsaCheckV1(paramsMap,
                AliPayClientConfig.alipay_public_key,
                AliPayClientConfig.charset,
                AliPayClientConfig.sign_type); //调用SDK验证签名
        if (signVerified) {
            // TODO 验签成功后，按照支付结果异步通知中的描述，对支付结果中的业务内容进行二次校验，校验成功后在response中返回success并继续商户自身业务处理，校验失败返回failure
//             获取交易号
            String out_trade_no = paramsMap.get("out_trade_no");
//            获取支付宝返回的支付金额
            String total_amount = paramsMap.get("total_amount");
//            获取当前appid
            String app_id = paramsMap.get("app_id");
//            获取支付宝的支付状态
            String trade_status = paramsMap.get("trade_status");
//             获取异步请求的notify_id
            String notify_id = paramsMap.get("notify_id");
//      根据out_trade_no(交易号)  + 支付方式 查询记录

            PaymentInfo paymentInfo = paymentInfoService.getPaymentInfo(out_trade_no, PaymentType.ALIPAY.name());
//          金额校验 对象校验 appId校验
            if (!ObjectUtils.isEmpty(paymentInfo) &&
                    new BigDecimal("0.01").compareTo(new BigDecimal(total_amount)) == 0
                    && AliPayClientConfig.app_id.equals(app_id)) {
//      响应状态 校验 TRADE_SUCCESS(支持退款) TRADE_FINISHED(不支持退款)
                if ("TRADE_SUCCESS".equals(trade_status) || "TRADE_FINISHED".equals(trade_status)) {
//          存储异步调用的唯一标识(每次执行的notify_id 不会改变) setIfAbsent关键字已经存在 下一次就不能再次插入数据了
                    Boolean res = redisTemplate.opsForValue().setIfAbsent(notify_id, notify_id, 1464, TimeUnit.MINUTES);
                    if (res) {

//                        修改支付记录的状态为PAID
                        boolean flag = paymentInfoService.paySuccess(out_trade_no, PaymentType.ALIPAY.name(), paramsMap);
//                  是否修改成功
                        if (flag) {
                            return "success";  // 返回给支付宝(success字符串) 不然会激活支付宝的重发机制1464 分钟
                        }
                    }
                }
            }

//      响应条件  必须是 TRADE_SUCCESS 或 TRADE_FINISHED
            return "failure";  //返回给支付宝 进行重发
        } else {
            // TODO 验签失败则记录异常日志，并在response中返回failure.
            System.out.println("验签失败");
            return "failure";  //返回给支付宝 进行重发
        }


    }


    /***
     * 同步回调
     * /api/payment/alipay/callback/return
     * @param
     * @return
     */
    @GetMapping("/callback/return")
    public String callbackReturn() {
//重定向到成功页面         http://payment.gmall.com/pay/success.html
        return "redirect:" + AliPayClientConfig.RETURN_ORDER_URL;
    }


    /**
     * 调用支付宝接口 返回支付页面(字符串)
     * /api/payment/alipay/submit/{orderId}
     *
     * @param orderId
     * @return
     */
    @RequestMapping("/submit/{orderId}")
    @ResponseBody
    public String submitOrder(@PathVariable Long orderId) {
        String from = alipayService.createAliPay(orderId);
        return from;
    }

}
